package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.cache.ShipmentCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.cache.BatchRuleCache;
import com.arpa.wms.cache.GoodsCache;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.consts.PropertyConst;
import com.arpa.wms.domain.dto.BatchRuleDTO;
import com.arpa.wms.domain.dto.BatchRuleFormDTO;
import com.arpa.wms.domain.entity.BatchRule;
import com.arpa.wms.domain.enums.DeleteFlagEnum;
import com.arpa.wms.domain.enums.StatusEnum;
import com.arpa.wms.domain.vo.BatchRuleVO;
import com.arpa.wms.mapper.BatchRuleMapper;
import com.arpa.wms.service.IBatchRuleService;
import com.arpa.wms.service.IGoodsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 批次规则 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-11
 */
@Service
public class BatchRuleServiceImpl extends ServiceImpl<BatchRuleMapper, BatchRule> implements IBatchRuleService {

    private final PartyCache partyCache;
    private final ShipmentCache shipmentCache;

    @Autowired
    private GoodsCache goodsCache;

    private final BatchRuleCache batchRuleCache;

    private static final String BATCHRULE_NAME_MANAGE = "同一所属机构下批次规则名称不能重复";
    @Autowired
    @Lazy
    private IGoodsService iGoodsService;

    public BatchRuleServiceImpl(PartyCache partyCache, ShipmentCache shipmentCache,BatchRuleCache batchRuleCache) {
        this.partyCache = partyCache;
        this.batchRuleCache = batchRuleCache;
        this.shipmentCache = shipmentCache;
    }


    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(BatchRule entity) {
        if(StrUtil.isBlank(entity.getCode())){
            entity.setCode(IdUtil.simpleUUID());
        }
        entity.setGroupCode(UserUtil.getBranchCode());
        if(StrUtil.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
            entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
        }
        //校验规则名称是否重复
        Integer num = baseMapper.selectCount(new LambdaQueryWrapper<BatchRule>().eq(BatchRule::getName, entity.getName())
                .eq(BatchRule::getGroupCode,UserUtil.getBranchCode())
                .eq(BatchRule::getShipmentCode,entity.getShipmentCode()));
        if (num > NumConst.NUM_ZERO) {
            throw new ServiceException(BATCHRULE_NAME_MANAGE);
        }
        entity.setGroupCode(UserUtil.getBranchCode());
        entity.setState(StatusEnum.UNACTIVE.getValue());
        entity.setModifiedBy(UserUtil.getCode());
        entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));

        batchRuleCache.flushAllCacheByGroupCode(entity.getGroupCode());
        batchRuleCache.flushAllCacheByShipmentCode(entity.getShipmentCode());

        return super.save(entity);
    }

    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(BatchRuleFormDTO entity) {
        //校验规则名称是否重复
        Integer num = baseMapper.selectCount(new LambdaQueryWrapper<BatchRule>()
                .eq(BatchRule::getName, entity.getName())
                .eq(BatchRule::getShipmentCode,entity.getShipmentCode())
                .ne(BatchRule::getCode, entity.getCode())
                .eq(BatchRule::getGroupCode,UserUtil.getBranchCode()));
        if (num != null  && num > 0) {
            throw new ServiceException(BATCHRULE_NAME_MANAGE);
        }
        batchRuleCache.flushCache(entity.getCode());
        BatchRule batchRule = BeanUtil.copyProperties(entity,BatchRule.class);
        batchRule.setModifiedBy(UserUtil.getCode());
        batchRule.setModifiedName(partyCache.translate(UserUtil.getCode()));
        return baseMapper.update(batchRule,new QueryWrapper<BatchRule>().lambda().eq(BatchRule::getCode,entity.getCode()).eq(BatchRule::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 查询列表
     * @param batchRuleDTO
     * @return
     */
    @Override
    public List<BatchRuleVO> queryList(BatchRuleDTO batchRuleDTO){
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StrUtil.isNotEmpty(batchRuleDTO.getSortField())){
            batchRuleDTO.setSortField(CommonUtil.camel2Underline(batchRuleDTO.getSortField()));
        }
        List<BatchRuleVO> batchRuleVOList = baseMapper.queryList(batchRuleDTO);
        if (IterUtil.isNotEmpty(batchRuleVOList)) {
            batchRuleVOList.forEach(r -> {
                r.setShipmentName(shipmentCache.translate(r.getShipmentCode()));
                StatusEnum enumByValue = StatusEnum.getEnumByValue(r.getStatus());
                if (null != enumByValue) {
                    r.setStatusName(enumByValue.getDesc());
                }
            });
        }



        return batchRuleVOList;
    }

    @Override
    public List<BatchRuleVO> queryByCodes(List<String> codes) {

        return baseMapper.queryByCodes(codes,UserUtil.getBranchCode());
    }

    @Override
    public List<BatchRuleVO> getListByCodes(List<String> codes) {

        return baseMapper.queryByCodes(codes,UserUtil.getBranchCode());
    }

    /**
     * 查询合计,包含总数
     * @param batchRuleDTO
     * @return
     */
    @Override
    public BatchRuleVO queryListSum(BatchRuleDTO batchRuleDTO){
        BatchRuleVO batchRuleVO = baseMapper.queryListSum(batchRuleDTO);
        return batchRuleVO;
    }
    /**
     * 批量删除
     * @param codes
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void batchdel(List<String> codes) {

        for(String code : codes){
            this.update(new UpdateWrapper<BatchRule>().lambda().eq(BatchRule::getCode, code).eq(BatchRule::getGroupCode,UserUtil.getBranchCode())
                    .set(BatchRule::getDeleted, 1));
        }
    }

    private int updateStaus(List<String> codes, StatusEnum active){
        int num = 0;
        boolean flag = false;
        if(IterUtil.isNotEmpty(codes)){
            for(String code: codes){
                if(active.getValue().equals(StatusEnum.ACTIVE.getValue())){
                    flag = this.update(new UpdateWrapper<BatchRule>().lambda().set(BatchRule::getState, active).set(BatchRule::getDeleted, DeleteFlagEnum.NOTDELETE.getCode())
                            .eq(BatchRule::getCode, code).eq(BatchRule::getGroupCode,UserUtil.getBranchCode()));
                }else {
                    flag = this.update(new UpdateWrapper<BatchRule>().lambda().set(BatchRule::getState, active)
                            .eq(BatchRule::getCode, code).eq(BatchRule::getGroupCode,UserUtil.getBranchCode()));
                }
                if(flag){
                    num++;
                }
                batchRuleCache.flushCache(code);
            }
        }
        return num;
    }
    /**
     *  根据批次code更新启用、停用状态
     * @param codes
     * @param active
     * @return
     */
    @Override
    public Map<String,Object> activeStatus(List<String> codes, StatusEnum active) {
        Map<String,Object> result = new HashMap<>();
        if(active.getValue().equals(StatusEnum.UNACTIVE.getValue())){
            List<Map<String,Integer>> useCount =  baseMapper.goodsUseCount(codes);

            Map<Boolean, List<String>> codesMap = codes.stream().collect(Collectors.groupingBy(r -> (useCount.stream().filter(c->StrUtil.equals(MapUtil.getStr(c,"lotNumber"),r)).findFirst()).isPresent()));

            List<String> notUse = codesMap.get(false);
            List<String> use = codesMap.get(true);
            if (IterUtil.isNotEmpty(notUse)) {
                int num = updateStaus(notUse, active);
                result.put(PropertyConst.SUCCESS, num);
            }
            if (IterUtil.isNotEmpty(use)) {
                result.put("fail", use.size());
                List<String> message = use.stream().map(r ->batchRuleCache.translate(r)).collect(Collectors.toList());
                result.put("msg", message);
            }
        }else {
            int num = updateStaus(codes, active);
            result.put(PropertyConst.SUCCESS,num);
        }
        return result;
    }






    /**
     * 查询VO
     * @param receiveItemCode
     * @return
     */
    @Override
    public BatchRuleVO findVoByreceiveItemCode(String receiveItemCode){
        BatchRuleVO batchRuleVO = baseMapper.findVoByreceiveItemCode(receiveItemCode,UserUtil.getBranchCode());
        return batchRuleVO;
    }

    @Override
    public BatchRuleVO findVoByGoods(String goodCode) {
        return baseMapper.findVoByGoods(goodCode);
    }


    /**
     * 通过code删除单位
     *
     * @param codes
     */
    @Override
    public Map<String,Object> removeByCode(List<String> codes) {

        Map<String,Object> result = new HashMap<>();
        int num = 0;
        List<BatchRuleVO> batchRuleVoS = queryByCodes(codes);
        List<String> notDelete = batchRuleVoS.stream().filter(info -> info.getDeleteFlag().intValue() == DeleteFlagEnum.NOTDELETE.getCode().intValue()).map(r -> {
            return r.getCode();
        }).collect(Collectors.toList());
        List<String> notDeleteName = notDelete.stream().map(code -> {
            return batchRuleCache.translate(code);
        }).collect(Collectors.toList());
        result.put("notDelete",notDeleteName);
        List<String> canDelete = codes.stream().filter(r -> !notDelete.contains(r)).collect(Collectors.toList());
        if(IterUtil.isNotEmpty(canDelete)){
            num = baseMapper.delete(new QueryWrapper<BatchRule>().lambda().in(BatchRule::getCode, canDelete).eq(BatchRule::getGroupCode,UserUtil.getBranchCode()));
        }
        if(num > 0){
            for (String code:codes) {
                batchRuleCache.flushCache(code);
            }
        }
        result.put(PropertyConst.SUCCESS,num);
        return result;
    }

    /**
     * 获取货主批次信息
     *
     * @param shipmentCode
     * @return
     */
    @Override
    public List<Map<String, Object>> findByShipmentCode(String shipmentCode) {
        List<Map<String, Object>> batchs = batchRuleCache.getAllByShipmentCode(shipmentCode);
        //对未启用批次规则进行过滤
        if (IterUtil.isNotEmpty(batchs)) {
            batchs = batchs.stream().filter(r -> NumConst.NUM_ZERO.toString().equals(r.get("state"))).collect(Collectors.toList());
        }
        return batchs;
    }

    /**
     * 获取批次信息
     *
     * @param code
     * @return
     */
    @Override
    public BatchRuleVO getByCode(String code) {
        BatchRule entity = getOne(new QueryWrapper<BatchRule>().lambda().eq(BatchRule::getCode,code).eq(BatchRule::getGroupCode,UserUtil.getBranchCode()));
        BatchRuleVO batchRuleVO = BeanUtil.copyProperties(entity,BatchRuleVO.class);
        batchRuleVO.setShipmentName(shipmentCache.translate(batchRuleVO.getShipmentCode()));
        return batchRuleVO;
    }

}
